﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.Win32;
using OntologyCache;
using UCSD_BioLit;
using System.ComponentModel;
using System.Xml;

namespace biolit_config
{
    /// <summary>
    /// Interaction logic for SettingsDialog.xaml
    /// </summary>
    public partial class SettingsDialog : Window
    {
        #region private properties
        private Boolean m_needToDownloadOntologies = false;
        List<DownloadHistory> ontDownloadList = null;
        #endregion private properties

        #region public properties

        public Boolean needToDownloadOntologies{
            get { return m_needToDownloadOntologies; }
        }
        #endregion public properties

        #region public methods
       public SettingsDialog()
        {
            InitializeComponent();
        }


        /// <summary>
        /// OntologyTabLoad - handles the initialization of the dialog
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>

        public void OntologyTabLoad(object sender, EventArgs e)
        {
            ConfigSettings cs = Biolit_Settings.Settings;
            SortDescription sortDescription = new SortDescription("Name", ListSortDirection.Ascending);
            GetAvailableOntologiesList();
            SelectedOntologies.DisplayMemberPath = "Name";
            if (Globals.ThisAddIn.m_SelectedOntologies != null)
            {
                foreach (OntList ontology in Globals.ThisAddIn.m_SelectedOntologies)
                {
                    OntList cachedOntologies = new OntList();
                    cachedOntologies.Name = ontology.Name;
                    cachedOntologies.ID = ontology.ID;
                    cachedOntologies.Version = ontology.Version;
                    cachedOntologies.Format = ontology.Format;
                    cachedOntologies.Source = ontology.Source;
                    SelectedOntologies.Items.Add(cachedOntologies);
                }
            }
            SelectedOntologies.Items.SortDescriptions.Add(sortDescription);
            NCBITB.IsChecked = cs.NCBI;
            PDBTB.IsChecked = cs.ProteinDataBank;
            IDTB.IsChecked = cs.UniProt;

            workOfflineCB.IsChecked = cs.AlwaysOffline;
            alwaysRunCB.IsChecked = cs.AutoStart;
            NCBITB.IsChecked = cs.NCBI;
            PDBTB.IsChecked = cs.ProteinDataBank;
            IDTB.IsChecked = cs.UniProt;
            //matchingInlineCB.IsChecked = cs.InlineMatching;
            FillAvailableDownloadURLs();

        }

         #endregion public methods

         #region private methods

        /// <summary>
        /// AddOntology_Click - Handles inserting the selected ontology to the list of ontologies to download
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>

        private void AddOntology_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                ((OntList)AvailableOntologies.SelectedItem).DownloadURL = Biolit_Settings.Settings.SelectedDownloadURL.URL;
                AddOntologyIfUnique(((OntList)AvailableOntologies.SelectedItem));
                if (AvailableOntologies.SelectedItem != null)
                {
                    AvailableOntologies.Items.Remove(AvailableOntologies.SelectedItem);
                    Biolit_Settings.Settings.RemoveFromOntology((OntList)AvailableOntologies.SelectedItem);
                }
            }
            catch (Exception)
            {
            }

        }

        /// <summary>
        /// AddOntologyIfUnique - Adds a new ontology to the list of selected ontologies in the dialog
        /// </summary>
        /// <param name="Ontology name"></param>
        /// <param name="Ontology ID"></param>
        private void AddOntologyIfUnique(OntList ontology)
        {
            int index = 0;
            Boolean alreadyInSelectedList = false;

            //check to see if this item is already on the list, we only want it once
            while (index < SelectedOntologies.Items.Count)
            {
                OntList currentItem = (OntList)SelectedOntologies.Items.GetItemAt(index);

                if (currentItem.Name == ontology.Name)
                {
                    alreadyInSelectedList = true;
                    break;
                }
                else
                    index++;
            }

            //if it is not in the list, add it
            if (alreadyInSelectedList == false)
            {
                SelectedOntologies.Items.Add(ontology);
                
            }
        }

        /// <summary>
        /// RemoveOntology_Click - Removes the selected ontology from the list
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void RemoveOntology_Click(object sender, RoutedEventArgs e)
        {
            if( SelectedOntologies.SelectedItem != null)
                SelectedOntologies.Items.Remove(SelectedOntologies.SelectedItem);
            Globals.ThisAddIn.m_SelectedOntologies.Remove((OntList)SelectedOntologies.SelectedItem);
            GetAvailableOntologiesList();
            

        }

        /// <summary>
        /// OkaySettingsButton_Click - This dismisses the dialog, updates the settings, and saves them out
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OkaySettingsButton_Click(object sender, RoutedEventArgs e)
        {
            ConfigSettings cs = Biolit_Settings.Settings;

            cs.NCBI = (bool) NCBITB.IsChecked;
            cs.ProteinDataBank = (bool)PDBTB.IsChecked;
            cs.UniProt = (bool)IDTB.IsChecked;

            cs.AlwaysOffline = (bool)workOfflineCB.IsChecked;
            cs.AutoStart = (bool)alwaysRunCB.IsChecked;
            //cs.InlineMatching = (bool)matchingInlineCB.IsChecked;

            int index = 0;
            OntList[] newSelectedArray = new OntList[SelectedOntologies.Items.Count];
            m_needToDownloadOntologies = false;

            int newListIndex = 0;

            for (newListIndex = 0; newListIndex < SelectedOntologies.Items.Count; newListIndex++)
            {
                Boolean foundItem = false;
                OntList currentItem = (OntList)SelectedOntologies.Items.GetItemAt(newListIndex);

                List<OntList>.Enumerator ontologyEnumerator = Globals.ThisAddIn.m_SelectedOntologies.GetEnumerator();

                while ( ontologyEnumerator.Current != null)
                {
                    if (ontologyEnumerator.Current.ID == currentItem.ID &&
                        ontologyEnumerator.Current.Name == currentItem.Name)
                    {
                        foundItem = true;
                        break;
                    }
                    ontologyEnumerator.MoveNext();
                }

                if (foundItem == false)
                {
                    m_needToDownloadOntologies = true;
                    break;
                }
            }

            // if we need to download ontologies, we also need to update the list to reflect the ListBox items
            if (m_needToDownloadOntologies == true || Globals.ThisAddIn.m_SelectedOntologies.Count != SelectedOntologies.Items.Count)
            {
                Globals.ThisAddIn.m_SelectedOntologies.Clear();

                while (index < SelectedOntologies.Items.Count)
                {
                    OntList currentItem = (OntList)SelectedOntologies.Items.GetItemAt(index);
                    Globals.ThisAddIn.m_SelectedOntologies.Add(currentItem);
                    
                    index++;
                }
                
            }

            Biolit_Settings.StoreSettings();

            settingsDialog.Close();

            
        }

        private void FillAvailableDownloadURLs()
        {
            ConfigSettings cs = Biolit_Settings.Settings;
            if (cs.AvailableDownloadURLs.Length > 0)
            {
                OntologyLocations.Items.Clear();
                foreach (OntologyDownloadLocation downloadURL in cs.AvailableDownloadURLs)
                {
                    int comboxBoxIndex;
                    ComboBoxItem urlItem = new ComboBoxItem();
                    urlItem.Content = downloadURL.Name;
                    urlItem.Tag = downloadURL;
                    comboxBoxIndex = OntologyLocations.Items.Add(urlItem);
                    if (downloadURL.Name.Equals(cs.SelectedDownloadURL.Name))
                    {
                        OntologyLocations.SelectedIndex = comboxBoxIndex;
                    }
                }
            }
        }
        /// <summary>
        /// okayButton_Click - This dismisses the dialog used to add a new URL
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void okayButton_Click(object sender, RoutedEventArgs e)
        {
            ((Window)((Button)sender).Tag).DialogResult = true;
            ((Window)((Button)sender).Tag).Close();
        }

        /// <summary>
        /// Navigate_OnClick - Launches the default browser to enable the user to submit suggestions of databases
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Navigate_OnClick(object sender, RoutedEventArgs e)
        {
            System.Diagnostics.Process.Start((sender as Hyperlink).NavigateUri.ToString());
        }

        /// <summary>
        /// LoadOntologyFile_Selected - Handles the user selection of a different place to download ontologies from
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>

        private void LoadOntologyFile_Selected(object sender, RoutedEventArgs e)
        {
            // Configure open file dialog box
            OpenFileDialog dlg = new OpenFileDialog();
            dlg.FileName = ""; // Default file name
            dlg.DefaultExt = ".obo"; // Default file extension
            dlg.Filter = "Ontology OBO Files (*.obo)|*.obo";

            // Show open file dialog box
            Nullable<bool> result = dlg.ShowDialog();

            // Process open file dialog box results
            if (result == true)
            {
                string targetOBOFileName = System.IO.Path.Combine(Biolit_Settings.Settings.OBO_DWNLDS, dlg.SafeFileName);
                //string targetDATFileName = System.IO.Path.Combine(Biolit_Settings.Settings.OBO_DWNLDS, dlg.SafeFileName.TrimEnd('.', 'o', 'b', 'o') + ".dat");
                string targetDATFileName = string.Empty;
                string ontologyName = string.Empty;
                if (dlg.SafeFileName.ToLower().EndsWith(".obo"))
                {
                    targetDATFileName = System.IO.Path.Combine(Biolit_Settings.Settings.OBO_DWNLDS, dlg.SafeFileName.Substring(0, dlg.SafeFileName.Length - 4) + ".dat");
                    int position = targetDATFileName.LastIndexOf('\\');
                    string ontFileName = targetDATFileName.Substring(position + 1);
                    ontologyName = ontFileName.Remove(ontFileName.LastIndexOf('.'));
                }
                if (System.IO.File.Exists(targetOBOFileName) != true)
                    System.IO.File.Copy(dlg.FileName, targetOBOFileName);
                else
                {
                    // ask the user whether they want to replace
                    // would be good to check the version of the ontology and file stamp
                    // and provide that information to the user, so that they can make an informed decision
                    // 
                    // for now replace the file

                    System.IO.File.Copy(dlg.FileName, targetOBOFileName, true);
                }

                OntologyInfo thetags = null;
                if (!String.IsNullOrEmpty(targetDATFileName))
                    thetags = CacheManager.LoadTagsFromCache(targetDATFileName, true, ontologyName);

                if (thetags != null)
                {
                    thetags.OntologyName = ontologyName;
                    Globals.ThisAddIn.m_Ontologies.Add(thetags);
                    OntList newOntology = new OntList(ontologyName, string.Empty, string.Empty, "obo", "Local File");
                    UpdateDownloadHistory(ontologyName, "OBO");
                    Globals.ThisAddIn.m_SelectedOntologies.Add(newOntology);
                    AddOntologyIfUnique(newOntology);
                }
                else
                {
                    // an error ocurred loading the ontology, need to inform the user
                }
            }

        }
        private void UpdateDownloadHistory(string OntologyName, string Format)
        {
            if (!String.IsNullOrEmpty(OntologyName) && !String.IsNullOrEmpty(Format))
            {
                if (Biolit_Settings.Settings != null)
                {
                    ConfigSettings cs = Biolit_Settings.Settings;
                    if (cs.DownloadedOntologies != null)
                        ontDownloadList = cs.DownloadedOntologies.ToList();
                }

                if (ontDownloadList == null)
                    ontDownloadList = new List<DownloadHistory>();
                ontDownloadList.Add(new DownloadHistory(string.Empty, OntologyName, string.Empty, Format, "Success", Convert.ToString(System.DateTime.Now), string.Empty, string.Empty, "Local File"));
                Biolit_Settings.Settings.DownloadedOntologies = ontDownloadList.ToArray();
                Biolit_Settings.StoreSettings();
            }
        }
        private void DownloadOntologyFile_Selected(object sender, RoutedEventArgs e)
        {
            DownloadOntology ontologyDownloadDialog = new DownloadOntology();

            ontologyDownloadDialog.ShowDialog();
        }

        private void AvailableOntologies_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            AddOntology_Click(sender, e);
        }

         

        private void btnDownloadLocation_Click(object sender, RoutedEventArgs e)
        {
            OntologyDownloadManagement manageDownloadLocationsDialog = new OntologyDownloadManagement();
            manageDownloadLocationsDialog.ShowDialog();
            FillAvailableDownloadURLs();
        }

        private void GetAvailableOntologiesList()
        {
            AvailableOntologies.Items.Clear();
            SortDescription sortDescription = new SortDescription("Name", ListSortDirection.Ascending);
            if (Biolit_Settings.Settings.AvailableOntologies != null)
            {
                bool foundOntList = false;
                foreach (OntList ontology in Biolit_Settings.Settings.AvailableOntologies)
                {

                    if (Globals.ThisAddIn.m_SelectedOntologies != null)
                    {
                        foreach (OntList ontologyList in Globals.ThisAddIn.m_SelectedOntologies)
                        {
                            if (ontologyList.Name.Equals(ontology.Name, StringComparison.CurrentCultureIgnoreCase))
                            {
                                foundOntList = true;
                                break;
                            }
                            foundOntList = false;
                        }
                    }
                    if (SelectedOntologies.Items.Count > 0)
                    {
                        foreach (OntList lvi in SelectedOntologies.Items)
                        {
                            if (lvi.Name.Equals(ontology.Name, StringComparison.CurrentCultureIgnoreCase))
                            {
                                foundOntList = true;
                                break;
                            }
                            foundOntList = false;
                        }
                    }
                    if (false == foundOntList)
                    {
                        OntList cachedOntologies = new OntList();
                        cachedOntologies.Name = ontology.Name;
                        cachedOntologies.ID = ontology.ID;
                        cachedOntologies.Version = ontology.Version;
                        cachedOntologies.Format = ontology.Format;
                        cachedOntologies.Source = ontology.Source;
                        AvailableOntologies.Items.Add(cachedOntologies);
                    }

                }
            }

            AvailableOntologies.DisplayMemberPath = "Name";
            //SelectedOntologies.DisplayMemberPath = "Name";
            AvailableOntologies.Items.SortDescriptions.Add(sortDescription);
        }

        private void OntologyLocations_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (OntologyLocations.SelectedIndex != -1)
            {
                ConfigSettings configSettings = Biolit_Settings.Settings;
                OntologyDownloadLocation OntDownloadLocation = ((ComboBoxItem)OntologyLocations.SelectedItem).Tag as OntologyDownloadLocation;
                configSettings.SelectedDownloadURL.Name = OntDownloadLocation.Name;
                configSettings.SelectedDownloadURL.URL = OntDownloadLocation.URL;
                Biolit_Settings.StoreSettings();
            }

        }
         #endregion private methods
    }
}
